import { ref, Ref, computed, ComputedRef } from 'vue';
import { useStore } from 'vuex';
import sendToUnity from '/@/core/communication/SendToUnity';
import { Platform, SendMessageType } from '/@/config/DeclareGlobal';
import { useWebsocketStoreWithOut } from '/@/store/modules/thingsboard/websocket';

/**
 * Node-RED 连接和消息处理模块
 */

// 添加WebSocket引用
const nodeRedWebSocket: Ref<WebSocket | null> = ref(null);

// 页面可见性状态和消息处理时间戳
const isPageVisible = ref(true);
const pageHiddenTimestamp = ref(0); // 页面隐藏的时间戳
const MESSAGE_PROCESS_DURATION = 3000; // 页面隐藏后继续处理消息的时长(3秒)

// 当前环境模式
const isWebGL = ref(true); // 默认使用WebGL模式

// 消息去重相关
const lastMessages = ref<Record<string, number>>({});
const MESSAGE_TTL = 1000; // 1秒内相同的消息视为重复

// 任务完成消息去重
const lastTaskData = ref<Record<string, any>>({});

let storeInstance: any = null;

/**
 * 初始化 Node-RED WebSocket 连接
 */
export function connectToNodeRed() {
  try {
    // 确保 store 已初始化
    if (!storeInstance) {
      storeInstance = useStore();
    }

    // 从store获取Node-RED WebSocket URL，与MotorHealth.vue中获取WebSocket URL的方式保持一致
    const websocketStore = useWebsocketStoreWithOut();
    const wsUrl = websocketStore.getNodeRedWsUrl;

    console.log('正在连接到Node-RED WebSocket:', wsUrl);

    // 检查URL是否有效
    if (!wsUrl || wsUrl === 'ws://:1880/taskFinish') {
      throw new Error('无效的WebSocket URL: ' + wsUrl);
    }

    nodeRedWebSocket.value = new WebSocket(wsUrl);

    nodeRedWebSocket.value.onopen = () => {
      console.log('成功连接到Node-RED WebSocket');
    };

    nodeRedWebSocket.value.onmessage = (event) => {
      // 页面隐藏时检查是否超过处理时限
      if (!isPageVisible.value) {
        const timeSinceHidden = Date.now() - pageHiddenTimestamp.value;
        if (timeSinceHidden > MESSAGE_PROCESS_DURATION) {
          console.log('页面隐藏超过3秒，忽略Node-RED消息');
          return;
        }
      }

      const message = event.data;
      console.log('收到Node-RED原始消息:', message);

      // 尝试解析消息
      let parsedMessage;
      try {
        parsedMessage = typeof message === 'string' ? JSON.parse(message) : message;
      } catch (error) {
        console.error('解析Node-RED消息失败:', error);
        return;
      }

      // 消息去重
      const messageHash = JSON.stringify(parsedMessage);
      const now = Date.now();

      if (
        lastMessages.value[messageHash] &&
        now - lastMessages.value[messageHash] < MESSAGE_TTL
      ) {
        console.log('忽略重复消息:', messageHash);
        return;
      }

      // 记录当前消息
      lastMessages.value[messageHash] = now;

      // 准备发送给Unity的消息
      const unityMessage = {
        type: SendMessageType.TaskAssignment,
        platform: Platform.web2unity,
      };

      // 根据当前模式设置data格式
      if (isWebGL.value) {
        // WebGL模式 - 发送对象
        unityMessage.data = parsedMessage;
      } else {
        // Unity模式 - 发送字符串
        unityMessage.data = JSON.stringify(parsedMessage);
      }

      // 发送给Unity
      sendToUnity.send(unityMessage);
      console.log('已转发任务分配消息到Unity:', unityMessage);
    };

    nodeRedWebSocket.value.onerror = (error) => {
      console.error('Node-RED WebSocket错误:', error);
    };

    nodeRedWebSocket.value.onclose = () => {
      console.log('Node-RED WebSocket连接关闭');
      // 自动重连
      setTimeout(() => {
        console.log('尝试重新连接Node-RED WebSocket...');
        connectToNodeRed();
      }, 3000);
    };
  } catch (error) {
    console.error('创建Node-RED WebSocket失败:', error);
    // 出错时尝试重连
    setTimeout(() => {
      console.log('尝试重新连接Node-RED WebSocket...');
      connectToNodeRed();
    }, 5000);
  }
}

/**
 * 发送消息到 Node-RED
 * @param message 要发送的消息
 */
export function sendToNodeRed(message: any) {
  try {
    if (nodeRedWebSocket.value?.readyState === WebSocket.OPEN) {
      // 确保发送的是字符串
      const payload = typeof message === 'string' ? message : JSON.stringify(message);
      nodeRedWebSocket.value.send(payload);
      console.log('已发送消息到Node-RED:', payload);
    } else {
      console.warn('Node-RED WebSocket未连接，无法发送消息');
      // 尝试重新连接
      connectToNodeRed();
    }
  } catch (error) {
    console.error('发送消息到Node-RED失败:', error);
  }
}

/**
 * 处理任务完成消息
 * @param e 接收到的消息
 * @param isWebGLMode 当前是否为 WebGL 模式
 */
export function handleTaskComplete(e: any, isWebGLMode: boolean = true) {
  console.log('原始接收的任务完成消息:', e);

  // 设置当前模式
  isWebGL.value = isWebGLMode;

  // 尝试提取任务数据
  let taskData = null;

  // 根据当前模式使用不同的解析策略
  if (isWebGL.value) {
    // WebGL模式处理逻辑
    if (typeof e === 'string') {
      try {
        taskData = JSON.parse(e);
      } catch (error) {
        console.error('解析字符串失败:', error);
      }
    } else if (e && typeof e.data === 'string') {
      try {
        taskData = JSON.parse(e.data);
      } catch (error) {
        console.error('解析data字符串失败:', error);
      }
    } else if (e && typeof e.data === 'object') {
      taskData = e.data;
    }
  } else {
    // Unity模式处理逻辑
    if (e && typeof e === 'object' && e.taskFlow) {
      taskData = e;
    } else if (e && e.data && typeof e.data === 'object' && e.data.taskFlow) {
      taskData = e.data;
    }
  }

  // 验证并发送
  if (taskData?.taskFlow) {
    console.log('成功提取任务数据:', taskData);

    // 创建唯一标识符
    const taskKey = `${taskData.taskFlow}-${taskData.task || 'unknown'}-${taskData.tray || ''}`;
    const now = Date.now();

    // 检查是否是重复消息（5秒内）
    if (lastTaskData.value[taskKey] && now - lastTaskData.value[taskKey] < 5000) {
      console.log('忽略重复任务完成消息:', taskKey);
      return;
    }

    // 记录当前任务
    lastTaskData.value[taskKey] = now;

    // 补全必要字段
    const fullTaskData = {
      taskFlow: taskData.taskFlow,
      task: taskData.task || 'unknown',
      originTray: taskData.originTray || '', // 新增
      newTray: taskData.newTray || '', // 新增
      tray: taskData.tray || '',
      status: taskData.status || 'assigned',
    };

    // 发送给Node-RED
    sendToNodeRed(fullTaskData);
  } else {
    console.error('无法提取任务完成消息数据:', e);

    // 尝试直接发送原始消息
    try {
      console.warn('尝试直接发送原始消息到Node-RED');
      sendToNodeRed(e);
    } catch (error) {
      console.error('最终发送尝试失败:', error);
    }
  }
}

/**
 * 设置页面可见性状态监听器
 */
export function setupPageVisibilityListener() {
  const handleVisibilityChange = () => {
    const wasVisible = isPageVisible.value;
    isPageVisible.value = !document.hidden;
    console.log('页面可见性状态:', isPageVisible.value ? '可见' : '隐藏');
    
    // 记录页面隐藏的时间
    if (!isPageVisible.value) {
      pageHiddenTimestamp.value = Date.now();
    } else {
      // 页面可见时重置时间戳
      pageHiddenTimestamp.value = 0;
    }
  };

  document.addEventListener('visibilitychange', handleVisibilityChange);
}

/**
 * 设置当前环境模式
 * @param webGLMode 是否为 WebGL 模式
 */
export function setEnvironmentMode(webGLMode: boolean) {
  isWebGL.value = webGLMode;
}

/**
 * 获取 Node-RED WebSocket 实例
 */
export function getNodeRedWebSocket() {
  return nodeRedWebSocket;
}
